package com.justgame.project.base.auth;


import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.justgame.project.cloud.common.constant.Auth2Token;
import com.justgame.project.cloud.common.constant.Const;
import com.justgame.project.cloud.common.exception.Exc;
import com.justgame.project.cloud.common.util.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Set;


/**
 * 身份认证
 */
@Component
@Slf4j
public class Auth2Realm extends AuthorizingRealm {

    public static final List<Integer> BAN = Arrays.asList(300, 301, 302, 399);
    @Resource
    private RedisUtil redisUtil;

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof Auth2Token;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        log.info(" - - - - - - - - 开始授权 - - - - - - - - ");
        String UserId = ShiroUtils.getUserId();
        log.info("UserID:{{}}", UserId);
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        Set<String> Role = redisUtil.hGet(Const.KEY_USER_ROLES, UserId);
        log.info("Roles:{{}}", JSONObject.toJSONString(Role));
        info.setRoles(Role);
        log.info(" - - - - - - - - 授权结束 - - - - - - - - ");
        return info;
    }


    /**
     * 验证业务逻辑
     *
     * @param token
     * @return
     * @throws AuthenticationException
     */

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //        获取TOKEN
        String accessToken = (String) token.getPrincipal();
        //        Token = 空
        if (StringUtils.isBlank(accessToken)) {
            throw new Exc(Const.CODE_TOKEN_EMPTY_CHINESE, Const.CODE_TOKEN_EMPTY);
        }
        String userid = JWT.decode(accessToken).getClaim("userid").asString();
        Object USER = JSONObject.parse(redisUtil.get(Const.KEY_REDIS_TOTAL_USER + userid));
        //        id不存在
        if (!ObjUtil.checkId(USER)) {
            throw new Exc(Const.CODE_TOKEN_MISMATCH_CHINESE, Const.CODE_TOKEN_MISMATCH);
        }
        String id = null;
        Integer status = null;
        try {
            id = BeanUtils.getProperty(USER, "id");
            status = Integer.parseInt(BeanUtils.getProperty(USER, "statusId"));
        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            e.printStackTrace();
            status = 200;
        }


        //        Token过期
        if (ShiroUtils.isExpiredToken(accessToken, userid)) {
            Date date = JWT.decode(accessToken).getExpiresAt();
            /* 换算成分 */
            long minutes = new Date(System.currentTimeMillis() - date.getTime()).getMinutes();
            log.info("用户ID{{}} Token已过期{}", id, minutes);
            if (minutes <= 60) {
                String newToken = new TokenUtil().generate(id, Const.DEFAULT_SALT_TOKEN, Const.TIME_TIMEOUT_TOKEN);
                HttpContextUtil.getHttpResponse().setHeader("token", newToken);
                ShiroUtils.delToken(accessToken);
            } else {
                throw new Exc(Const.CODE_TOKEN_OUTDATED_CHINESE, Const.CODE_TOKEN_OUTDATED);
            }
        }

        //        禁止登录
        if (BAN.contains(status)) {
            throw new Exc(Const.CODE_TOKEN_BAN_CHINESE, Const.CODE_TOKEN_BAN);
        }

        //        放行
        return new SimpleAuthenticationInfo(USER, accessToken, getName());
    }

}
